module tb;

   parameter width = 16;
   
   logic [width-1:0] quotient, reminder;
   logic 	   done;
   

   logic 	   clk = 0;
   logic 	   rst, load;
   logic [width-1:0] a,b;
   logic 			 sign;
   
   div #(.width(width)) U_div(
							  // Outputs
							  .o_quotient			(quotient),
							  .o_reminder			(reminder),
							  .o_done				(done),
							  // Inputs
							  .clk					(clk),
							  .rst					(rst),
							  .i_load				(load),
							  .i_a					(a),
							  .i_b					(b),
							  .i_sign				(sign));
   
   always #5 clk = ~clk;
   
   initial
	 begin
		bit unsigned [64:0] i;
		bit [width-1:0] correct_quo, correct_rmd;
		
		
		rst = 1;
		#20 rst = 0;
		@(posedge clk);
		
		
		
		$display("============================== test unsigned div/mod ==============================");
		sign = 1'b0;
		for(i=0;i<={2*width{1'b1}};i++)
		  begin
			 {b,a} = i;
			 if(b === 0)
			   begin
				  correct_quo = '1;
				  correct_rmd = a;
			   end
			 else
			   begin
				  correct_quo = a/b;
				  correct_rmd = a % b;
			   end
			 
			 load <= 1'b1;
			 @(posedge clk);
			 load <= 1'b0;

			 @(posedge clk);
			 @(posedge clk);
			 
			 while(!done)
			   @(posedge clk);
			 
			 
			 // $display("%d / %d = %d...%d  <-> correct:%d...%d  => %s", 
			 // 		  a, b, quotient, reminder,
			 // 		  correct_quo, correct_rmd, (quotient===correct_quo && reminder===correct_rmd) ? "equal" : "not equal" );

			 if(quotient!==correct_quo || reminder!==correct_rmd)
			   begin
				  $display("%d / %d = %d...%d  <-> correct:%d...%d  => %s", 
				  		  a, b, quotient, reminder,
				  		  correct_quo, correct_rmd, (quotient===correct_quo && reminder===correct_rmd) ? "equal" : "not equal" );
				  $display("failed");
				  $finish;
			   end
			 
		  end

		$display("============================== test signed div/mod ==============================");
		sign = 1'b1;
		for(i=0;i<={2*width{1'b1}};i++)
		  begin
			 {b,a} = i;
			 if(b === 0)
			   begin
				  if($signed(a)>=0)
					correct_quo = '1;
				  else
					correct_quo = 1;
				  correct_rmd = a;
			   end
			 else
			   begin
				  correct_quo = $signed(a)/$signed(b);
				  correct_rmd = $signed(a) % $signed(b);
			   end
			 
			 load <= 1'b1;
			 @(posedge clk);
			 load <= 1'b0;

			 @(posedge clk);
			 @(posedge clk);
			 
			 while(!done)
			   @(posedge clk);
			 
			 
			 // $display("%d / %d = %d...%d  <-> correct:%d...%d  => %s", 
			 // 		  $signed(a), $signed(b), $signed(quotient), $signed(reminder),
			 // 		  $signed(correct_quo), $signed(correct_rmd), (quotient===correct_quo && reminder===correct_rmd) ? "equal" : "not equal" );

			 if(quotient!==correct_quo || reminder!==correct_rmd)
			   begin
				  $display("%d / %d = %d...%d  <-> correct:%d...%d  => %s", 
			 			   $signed(a), $signed(b), $signed(quotient), $signed(reminder),
			 			   $signed(correct_quo), $signed(correct_rmd), (quotient===correct_quo && reminder===correct_rmd) ? "equal" : "not equal" );
				  
				  $display("failed");
				  $finish;
			   end
			 
		  end // for (int i=0;i<1;i++)

		$display("==================== passed ====================");
		$finish;
	 end

   
endmodule // tb
